package morrior

import (
	"fmt"
	"iot-base/common/fsm"
	"net"
	"strings"
	"sync"
	"time"
)

func edgePrepare(pFSM *fsm.FSMInstance) {
	//tip, _ := pFSM.GetContext().GetString("targetIP")
	//tport, _ := pFSM.GetContext().GetInt("targetPort")
	pFSM.NotifyEvent("perpareOK")
	/*
		tip, _ := pFSM.GetContext().GetString("targetIP")
		tport, _ := pFSM.GetContext().GetInt("targetPort")
		netType, _ := pFSM.GetContext().GetString("netType")

		seq, _ := pFSM.GetContext().GetString("seq")
		cons, _ := pFSM.GetContext().Get("connectionInfos")
		//client则开启一个端口 listen
		if netType == "tcp" {
			tcpAddr, _ := net.ResolveTCPAddr("tcp4", tip+":"+strconv.Itoa(tport))
			conn, err := net.DialTCP("tcp",nil,tcpAddr)
			if err != nil {
				fmt.Println("Listen tcp server failed,err:", err)
				return
			}

		}*/

}
func BeginEdge(pwg *sync.WaitGroup, kcpConnection net.Conn) {
	//建立状态机
	var con EdgeConnection
	pCon := &con
	con.pConnection = NewConnection(kcpConnection, 0, pCon.OnTCEdgeData, pCon.onTCEdgeCmd, pCon.onTCEdgeErr, pwg)

	fmt.Println("send begin-----------")
	con.pConnection.SendData(0, BEGIN, nil)
	pInstance := begin(pwg, con.pConnection)
	if pInstance != nil {
		pInstance.GetContext().Set("role", "edge")
	}
}

type EdgeConnection struct {
	pConnection *Connection
}

func (pConnection *EdgeConnection) OnTCEdgeData(pPro *MProBody, data []byte, seq uint32) {
	pConn := pConnection.pConnection
	//fmt.Println("------kcp connection----data-----------", len(data), seq)
	if pConn != nil && pConn.pfsm != nil {
		id := fmt.Sprintf("cseq.%d", seq)
		clientCon, _ := pConn.pfsm.GetContext().Get(id)
		if clientCon != nil {
			pClient, _ := clientCon.(net.Conn)
			if pClient != nil {
				err := sendful(pClient, data)
				//fmt.Println("send to fake----------", len(data), seq, err)
				if err != nil {
					fmt.Println("send close socket--------", id, seq, err)
					pConn.SendData(seq, ERROR_ON_CONNECTION_SEND, nil)
				}
			}
		} else {
			fmt.Println("client not found--------", id)
		}

	} else {
		fmt.Println("client not found---2-----", pConn)
	}
}

func (pConnection *EdgeConnection) onTCEdgeCmd(pPro *MProBody, ctype byte, seq uint32) {

	id := fmt.Sprintf("cseq.%d", seq)
	fmt.Println("-------edge-----cmd----", ctype, seq)
	mapClient, _ := pConnection.pConnection.pfsm.GetContext().Get(id)
	switch ctype {
	case BEGIN_MIRROR:
		cmd := string(pPro.Body)
		fmt.Println("-------edge-----cmd----", cmd)
		if mapClient != nil {
			return
		} else {
			ntype, addr := parseMirrorID(cmd)
			if ntype != "" {
				client, err := net.DialTimeout(strings.ToLower(ntype), addr, time.Duration(5)*time.Minute)
				fmt.Println("-------=connect-----------", err)
				if client != nil && err == nil {
					fmt.Println("-------=connect------succ-----", err, seq)
					pConnection.pConnection.pfsm.GetContext().Set(fmt.Sprintf("cseq.%d", seq), client)
					go func(pConn net.Conn, seq uint32) {

						for {
							buf := make([]byte, 20*1000)
							rlen, err := pConn.Read(buf[:])
							//fmt.Println("edge get--from fake connection--------data-----", seq, rlen, err)
							if rlen > 0 && err == nil {
								pConnection.pConnection.SendData(seq, DATA, buf[:rlen])
							} else {
								pConnection.pConnection.SendData(seq, ERROR_ON_CONNECTION_RECV, nil)
								fmt.Println("error----fake connection---------", err)
								break
							}
						}

					}(client, seq)
				} else if err != nil {
					fmt.Println("-------error=connect------error-----", err)
				}

			}

		}
	case ERROR_ON_CONNECTION, ERROR_ON_CONNECTION_RECV, ERROR_ON_CONNECTION_SEND:
		pConnection.pConnection.pfsm.GetContext().Remove(id)
		closeConection(pPro.Type, mapClient)

	}
}

func (pConnection *EdgeConnection) onTCEdgeErr(seq uint32, err error) bool {
	fmt.Println("get error------kcp----", seq, err)
	return true
}
